import * as THREE from 'three'
import { mergeBufferGeometries } from 'three/examples/jsm/utils/BufferGeometryUtils.js'
import { LineMaterial } from 'three/examples/jsm/lines/LineMaterial.js'
import { GUI } from 'three/examples/jsm/libs/lil-gui.module.min.js'
import { Base, OrbitControls, State, AssetsManager, Plane, getBoundingBox } from '@/libs/mini3d'
import { Grid } from './components/grid'
import { BaseMap } from './components/map'
import { Line } from './components/line'
import { Lights } from './components/lights'
import { Wall } from './components/wall'
import { UpShader } from './shader/upShader/index'
import { SpreadShader } from './shader/spreadShader/index'
import { GradientShader } from './shader/gradientShader/index'
import _ from 'lodash'
import { Label2d } from '@/libs/mini3d/extra/label2d'
import config from '@/config'
import { geoProjection, transfromGeoJSON, center, exportGLTF } from './utils'
import { random } from './utils/utils'
import { geoMercator } from 'd3-geo'
import emitter from '@/libs/mini3d/utils/mitt'
import { ElMessage } from 'element-plus'
import 'element-plus/es/components/message/style/css'

export class Map3d extends Base {
  constructor(el, info, columnList) {
    console.log('three.js正在被创建~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~')
    super(el)
    this.assets = [
      // { name: 'province', type: 'file', path: './data/四川省.json' },
      // { name: 'city', type: 'file', path: './data/成都市.json' },
      { name: 'rotationBorder1', type: 'texture', path: './data/rotationBorder1.png' },
      { name: 'rotationBorder2', type: 'texture', path: './data/rotationBorder2.png' },
      { name: 'gzmap', type: 'texture', path: './data/gz-map.jpg' },
      { name: 'bg', type: 'texture', path: './data/bg.jpg' },
      { name: 'column', type: 'texture', path: './data/光柱.png' },
      { name: 'china', type: 'file', path: './data/中华人民共和国.json', cityName: '中国' },
    ]
    this.el = el
    this.info = info ? info : { name: 'china', type: 'file', path: './data/中华人民共和国.json', cityName: '中国' }
    this.camera.lookAt(...center, 0)
    this.camera.up.set(0, 0, 1)
    this.camera.position.set(-0.7545, -18.348, 17.5656)
    this.renderer.setClearColor(0x191919, 1)
    let ambientLight = new THREE.AmbientLight(0xffffff)
    this.scene.add(ambientLight)
    this.mainMap = {}
    this.columnGroup = {}
    // 城市的面group
    this.meshGroup = []
    this.gui = ''
    // 城市的线group
    this.lineGroup = []
    this.chooseMesh = null //标记鼠标拾取到的mesh
    this.chooseLine = null
    if (this.info.name == 'china') {
      this.isChina = true
    } else {
      this.isChina = false
    }
    this.assets.push(this.info)
    this.isMove = false
    this.down = false
    this.scale = 1
    this.columnList = columnList
    this.assetsManager = new AssetsManager(this, this.assets, {
      onProgress: (current, total) => {
        console.log(current, total)
      },
      onComplete: () => {
        console.log('加载完成', this.assetsManager)
        this.start()
      },
    })

    emitter.on('updateColumn', data => {
      this.scene.children?.forEach(item => {
        if (item.name == '柱状图') {
          for (let i = 0; i < item.children.length; i++) {
            item.children[i].geometry.dispose()
            item.children[i].material.dispose()
          }
          item.removeFromParent()
        }
      })
      this.columnList = data.column
      // 然后从新画一个柱状图
      if (data.column.length > 0) {
        this.createBar(data.column)
      }
    })
    emitter.on('startLoading', () => {
      emitter.off('updateColumn')
    })

    emitter.on('destroyThree', () => {
      this.destroyThreejs()
      emitter.off('destroyThree')
    })
  }
  start() {
    super.start()
    this.helperTools()
    let loadedItems = ''
    if (this.info.name == 'china') {
      loadedItems = this.assetsManager.loadedItems.china
    } else {
      loadedItems = this.assetsManager.loadedItems.province
    }
    this.create(loadedItems, this.isChina, this.info.cityName, this.columnList)
  }
  /**
   * 开启辅助工具
   */
  helperTools() {
    // 内存监测
    // let state = new State(this)
    // state.join()
    // 轨道控制器
    let orbit = new OrbitControls(this)
    this.orbitControls.target = new THREE.Vector3(...center, 0)
    orbit.join()
    // 坐标轴辅助
    // let axes = new THREE.AxesHelper(200)
    // axes.position.set(...center, 0)
    // this.scene.add(axes)
  }
  create(loadedItems, isChina, name, columnList) {
    // 添加雾
    this.scene.fog = new THREE.Fog(0x191919, 30, 70)
    // this.getCenterPoint()
    this.createPlane()
    this.createGrid()
    this.createChinaMap()
    // this.createProvinceMap()
    this.createMap(loadedItems, isChina, name, columnList)
    this.createLight()
    this.createRotateBorder()
    // this.createLabel()
    // this.createWall()
    this.label2d = new Label2d(this)
    this.tag = this.label2d.createTip()
    this.scene.add(this.tag)

    document.getElementsByClassName('appMap')[0].addEventListener('mousemove', this.change.bind(this))
    document.getElementsByClassName('appMap')[0].addEventListener('mousedown', () => {
      this.down = true
    })
    document.getElementsByClassName('appMap')[0].addEventListener('mouseup', () => {
      this.down = false
    })
    document.getElementsByClassName('appMap')[0].addEventListener('click', this.goProvince.bind(this))

    emitter.emit('loadingFinish')
  }
  change(event) {
    if (this.down) {
      this.isMove = true
    }
    if (this.chooseLine) {
      this.chooseLine.position.z = 0
    }
    if (this.chooseMesh) {
      // 把上次选中的mesh设置为原来的颜色 并且将高度变为原来的高度
      for (let i = 0; i < this.lineGroup.length; i++) {
        if (this.lineGroup[i]['name'] == this.chooseMesh.name) {
          this.lineGroup[i].position.z = 0
        }
      }
      if (this.columnGroup.children){
        for(let i = 0; i < this.columnGroup.children.length; i++){
          if (this.columnGroup.children[i]['name'] == this.chooseMesh.name) {
            this.columnGroup.children[i]['position']['z'] = 1.4
          }
        }
      }

      for (let i = 0; i < this.meshGroup.children.length; i ++) {
        if (this.meshGroup.children[i].children[0]['name'] == this.chooseMesh.name) {
          this.meshGroup.children[i].children[0].material[0].color = new THREE.Color(0x206ed5)
          this.meshGroup.children[i].children[0].material[1].color = new THREE.Color(0x0776a0)
          this.meshGroup.children[i].children[0].material[1].opacity = 0.533
          this.meshGroup.children[i].children[0].material[0].map = this.assetsManager.loadedItems.gzmap
          this.meshGroup.children[i].children[0].scale.set(1, 1, 1)
          this.meshGroup.children[i].children[0].position.z = 0
        }
        if (
          this.meshGroup.children[i].children[1] &&
          this.meshGroup.children[i].children[1]['name'] == this.chooseMesh.name
        ) {
          this.meshGroup.children[i].children[0].material[0].color = new THREE.Color(0x206ed5)
          this.meshGroup.children[i].children[0].material[1].color = new THREE.Color(0x0776a0)
          this.meshGroup.children[i].children[0].material[1].opacity = 0.533
          this.meshGroup.children[i].children[0].material[0].map = this.assetsManager.loadedItems.gzmap
          this.meshGroup.children[i].children[1].scale.set(1, 1, 1)
          this.meshGroup.children[i].children[1].position.z = 0
        }
      }
      // this.chooseLine.position.z = 0
    } else {
      // 没有选中mesh，隐藏标签
      this.tag.hide()
    }
    var Sx = event.offsetX //鼠标单击位置横坐标
    var Sy = event.offsetY //鼠标单击位置纵坐标
    //屏幕坐标转WebGL标准设备坐标
    var x = (Sx / window.innerWidth) * 2 - 1 //WebGL标准设备横坐标
    var y = -(Sy / window.innerHeight) * 2 + 1 //WebGL标准设备纵坐标
    var raycaster = new THREE.Raycaster()
    raycaster.setFromCamera(new THREE.Vector2(x, y), this.camera)
    var intersects = raycaster.intersectObjects(this.meshGroup.children, true)

    if (intersects.length > 0) {
      this.chooseMesh = intersects[0].object
      // 获取边框的尺寸，然后给弹框设置一个位置
      var boundingBox = new THREE.Box3().setFromObject(this.chooseMesh)
      let tagX = boundingBox.max.x + 3
      let tagY = (boundingBox.min.y + boundingBox.max.y) / 2
      let obj = {
        name: this.chooseMesh.name,
        allCount: 0,
        warnCount: 0,
        normalCount: 0,
      }
      for (let i = 0; i < this.columnList.length; i++) {
        if (this.columnList[i]['key'] == this.chooseMesh.name) {
          obj.allCount = this.columnList[i]['allCount']
          obj.warnCount = this.columnList[i]['warnCount']
          obj.normalCount = this.columnList[i]['normalCount']
        }
      }
      this.tag.show(obj, new THREE.Vector3(tagX, tagY, 0.1))
      // 当前选中的那一部分缩放
      var bottomZ = boundingBox.min.z
      // 缩放选中的省份或区域沿 Z 轴
      var scaleHeight = 2.0; // 沿 Z 轴缩放因子，可以根据需求调整  可能存在2块地，
      if (this.columnGroup.children){
        for(let i = 0; i < this.columnGroup.children.length; i++){
          if (this.columnGroup.children[i]['name'] == this.chooseMesh.name) {
            this.columnGroup.children[i]['position']['z'] += 0.8
          }
        }
      }

      for(let i = 0; i < this.meshGroup.children.length; i++) {
        if (this.meshGroup.children[i].children[0]['name'] == this.chooseMesh.name) {
          // 移动对象位置以使底部对齐
          this.meshGroup.children[i].children[0]['position']['z'] -= bottomZ - 0.1
          this.meshGroup.children[i].children[0]['scale']['z'] = scaleHeight
          this.meshGroup.children[i].children[0].material[0].color = new THREE.Color(0x367ad3)
          this.meshGroup.children[i].children[0].material[1].color = new THREE.Color(0x15bfff)
          this.meshGroup.children[i].children[0].material[1].opacity = 1
          this.meshGroup.children[i].children[0].material[0].map = this.assetsManager.loadedItems.bg
        }
        if (
          this.meshGroup.children[i].children[1] &&
          this.meshGroup.children[i].children[1]['name'] == this.chooseMesh.name
        ) {
          // 移动对象位置以使底部对齐
          this.meshGroup.children[i].children[1]['position']['z'] -= bottomZ - 0.1
          this.meshGroup.children[i].children[1]['scale']['z'] = scaleHeight
          this.meshGroup.children[i].children[0].material[0].color = new THREE.Color(0x367ad3)
          this.meshGroup.children[i].children[0].material[1].color = new THREE.Color(0x15bfff)
          this.meshGroup.children[i].children[0].material[1].opacity = 1
          this.meshGroup.children[i].children[0].material[0].map = this.assetsManager.loadedItems.bg
        }
      }

      // 边线位置移动
      var boundingBox2 = new THREE.Box3().setFromObject(this.chooseMesh)
      for (let i = 0; i < this.lineGroup.length; i++) {
        if (this.lineGroup[i]['name'] == this.chooseMesh.name) {
          this.lineGroup[i].position.z = boundingBox2.max.z - 1.38
        }
      }
    } else {
      this.chooseMesh = null
    }
  }
  goProvince(event) {
    if (this.isMove) {
      this.isMove = false
      return
    }
    this.isMove = false
    var Sx = event.offsetX //鼠标单击位置横坐标
    var Sy = event.offsetY //鼠标单击位置纵坐标
    //屏幕坐标转WebGL标准设备坐标
    var x = (Sx / window.innerWidth) * 2 - 1 //WebGL标准设备横坐标
    var y = -(Sy / window.innerHeight) * 2 + 1 //WebGL标准设备纵坐标
    var raycaster = new THREE.Raycaster()
    raycaster.setFromCamera(new THREE.Vector2(x, y), this.camera)
    var intersects = raycaster.intersectObjects(this.meshGroup.children, true)
    if (intersects.length > 0) {
      this.chooseMesh = intersects[0].object
      let tag = 0
      for (let i = 0; i < this.columnList.length; i++) {
        if (this.columnList[i]['key'] == this.chooseMesh.name) {
          tag = 1
        }
      }
      this.scene.children?.forEach(item => {
        if (
          item.name &&
          item.name !== this.chooseMesh.name &&
          item.type == 'Group' &&
          item.name !== '网格地面' &&
          tag
        ) {
          item.visible = false
        }
      })
      if (!tag) {
        ElMessage({
          showClose: true,
          message: '该区域下暂无设备',
          type: 'warning',
        })
        return
      }
      emitter.off('updateColumn')
      if (this.isChina) {
        emitter.emit('message', {
          name: 'province',
          type: 'file',
          path: `./data/${this.chooseMesh.name}.json`,
          cityName: this.chooseMesh.name,
        })
      } else {
        // 能直接使用
        let center = ''
        if (this.mainMap.coordinates.length) {
          for (let i = 0; i < this.mainMap.coordinates.length; i++) {
            if (this.mainMap.coordinates[i].name == this.chooseMesh.name) {
              center = this.mainMap.coordinates[i].center
              break
            }
          }
          emitter.emit('message', { name: 'city', center: center, cityName: this.chooseMesh.name })
        }
      }

      // this.assetsManager = new AssetsManager(this, [{ name: 'province', type: 'file', path:  `./data/${this.chooseMesh.name}.json` }], {
      //   onProgress: (current, total) => {
      //     console.log(current, total)
      //   },
      //   onComplete: () => {
      //     // console.log('加载完成', this.assetsManager)
      //     this.createMap(this.assetsManager.loadedItems.province, false, this.chooseMesh.name)
      //     this.createBar()
      //   },
      // })
    }
  }

  createGui() {}
  // 获取中心点位置
  getCenterPoint() {
    let data = transfromGeoJSON(this.assetsManager.loadedItems.province)
    let cityData = data.features.filter(item => item.properties.name === config.cityName)
    if (cityData.length) {
      this.mainMap.center = cityData[0].properties.centroid || [0, 0]
      localStorage.setItem('center', JSON.stringify(this.mainMap.center))
    }
  }
  createGrid() {
    // 添加网格
    let grid = new Grid(this, { position: new THREE.Vector3(...center, 0) })
    grid.gridGroup.rotateX(Math.PI / 2)
    grid.join()
  }
  createChinaMap() {
    try {
      let china = new BaseMap(this, {
        data: this.assetsManager.loadedItems.china,
        topFaceMaterial: new THREE.MeshBasicMaterial({
          color: 0x18263b,
          transparent: true,
          opacity: 0.2,
        }),
        // topFaceMaterial: shaderMaterial.getMaterial(),
        sideMaterial: new THREE.MeshBasicMaterial({
          color: 0x000000,
          transparent: true,
          opacity: 1,
        }),
        renderOrder: 2,
      })
      china.join()
    } catch (error) {
      console.log(error)
    }
  }
  createProvinceMap() {
    let province = new BaseMap(this, {
      data: this.assetsManager.loadedItems.province,
      topFaceMaterial: new THREE.MeshBasicMaterial({
        color: 0x18263b,
        transparent: true,
        opacity: 0.2,
        // depthTest: false,
      }),
      sideMaterial: new THREE.MeshBasicMaterial({
        color: 0x000000,
        transparent: true,
        opacity: 1,
      }),
      renderOrder: 2,
    })
    province.join()
    let provinceLine = new Line(this, {
      data: this.assetsManager.loadedItems.province,
      material: new THREE.LineBasicMaterial({ color: 0x6393bd }),
      // material: new LineMaterial({ color: 0x6393bd, linewidth: 0.002 }),
      // type: 'Line2',
      renderOrder: 5,
    })

    provinceLine.join()
    provinceLine.lineGroup.position.z += 0.32
  }
  // 将这一块通过传参数，画出不同的地图
  createMap(loadedItems, isChina, name, columnList) {
    let allGroup = new THREE.Group()
    try {
      const sideMaterial = new UpShader(this, {
        start: -0.2, // 开始点
        end: 0.6, // 结束点
        height: 0.4, // 光环高度
        maxTime: 6, // 最大时间
        speed: 0.2,
        color: new THREE.Color('#1A64E0'), // 颜色
        material: new THREE.MeshLambertMaterial({
          color: 0x011d4d,
          transparent: true,
          opacity: 1,
        }),
      })
      console.log('开始添加城市')
      let topFaceMaterial = new THREE.MeshPhongMaterial({
        color: 0x206ed5,
        map: this.assetsManager.loadedItems.gzmap,
        combine: THREE.MultiplyOperation,
        // emissive: 0x072534,
        transparent: true,
        opacity: 1,
      })

      let sideMaterials = new THREE.MeshPhongMaterial({
        color: 0x367ad3,
        // emissive: 0x0776a0,
        transparent: true,
        opacity: 0.533,
      })
      // this.gui = new GUI();
      // let guiParams = {
      //   topColor: '0x206ed5',
      //   sideColor: '0x0776a0',
      //   topOpacity: 1,
      //   sideOpacity: 0.533,
      // };
      // this.gui.addColor(guiParams, 'topColor').onChange((val) => {
      //   topFaceMaterial.color.set(val);
      // });
      // this.gui.addColor(guiParams, 'sideColor').onChange((val) => {
      //   sideMaterials.color.set(val);
      // });
      // this.gui.add(guiParams, 'topOpacity', 0, 1).onChange((val) => {
      //   topFaceMaterial.opacity = val;
      // });
      // this.gui.add(guiParams, 'sideOpacity', 0, 1).onChange((val) => {
      //   sideMaterials.opacity = val;
      // });
      // 添中间地图
      this.assetsManager.loadedItems.gzmap.wrapS = THREE.RepeatWrapping
      this.assetsManager.loadedItems.gzmap.wrapT = THREE.RepeatWrapping
      this.assetsManager.loadedItems.gzmap.flipY = false
      this.assetsManager.loadedItems.gzmap.rotation = THREE.MathUtils.degToRad(45)
      const scale = 0.128
      this.assetsManager.loadedItems.gzmap.repeat.set(scale, scale)
      let city = new BaseMap(this, {
        data: loadedItems,
        topFaceMaterial: topFaceMaterial,
        sideMaterial: sideMaterials,
        renderOrder: 6,
        depth: 0.6,
        isChina,
        name,
      })
      // console.log(JSON.stringify(getBoundingBox(city.mapGroup)))
      city.mapGroup.position.z += 0.1
      this.meshGroup = { ...city.mapGroup }
      this.mainMap.coordinates = city.getCoordinates()
      this.mainMap.box = getBoundingBox(city.mapGroup)
      // city.join()
      allGroup.add(city.mapGroup)
      let cityLine = new Line(this, {
        data: loadedItems,
        material: new LineMaterial({ color: 0xa3dcff, linewidth: 0.001 }),
        renderOrder: 20,
        type: 'Line2',
        isChina,
        name,
      })
      cityLine.lineGroup.position.z += 1.6
      this.lineGroup = [...cityLine.lineGroup.children]
      // cityLine.join()
      allGroup.add(cityLine.lineGroup)

      let cityLine2 = new Line(this, {
        data: loadedItems,
        material: new LineMaterial({ color: 0x347b9a, linewidth: 0.001 }),
        renderOrder: 20,
        type: 'Line2',
        isChina,
        name,
      })
      cityLine2.lineGroup.position.z += -0.2
      allGroup.add(cityLine2.lineGroup)
    } catch (error) {
      console.log(error)
    }

    allGroup.name = '地图'
    if (!this.isChina) {
      let mapBox = getBoundingBox(allGroup)
      let scale = 1
      let scaleY = 1
      if (mapBox.size.x > 22) {
        scale = (22 / mapBox.size.x).toFixed(2) - 0.15
      }
      if (mapBox.size.y > 22) {
        scaleY = (22 / mapBox.size.y).toFixed(2)
      }
      if (mapBox.size.x < 18) {
        scale = (22 / mapBox.size.x).toFixed(2)
      }
      if (scaleY < scale) {
        scale = scaleY
      }
      this.scale = scale
      allGroup.scale.set(scale, scale, 1)
      allGroup.position.x = -(mapBox.center.x * scale)
      allGroup.position.y += -(mapBox.center.y * scale)
    } else {
      this.scale = 1
    }
    if (columnList.length > 0) {
      this.createBar(columnList)
    }
    this.scene.add(allGroup)
  }
  createLight() {
    const lights = new Lights(this)
    lights.join()
  }
  createRotateBorder() {
    //
    let plane01 = new Plane(this, {
      width: 20,
      needRotate: true,
      rotateSpeed: 0.003,
      material: new THREE.MeshBasicMaterial({
        map: this.assetsManager.loadedItems.rotationBorder1,
        transparent: true,
        opacity: 1,
        side: THREE.DoubleSide,
        depthWrite: false,
      }),
      position: new THREE.Vector3(...center, 0.33),
    })
    plane01.mesh.renderOrder = 6
    plane01.join()
    //
    let plane02 = new Plane(this, {
      width: 16,
      needRotate: true,
      rotateSpeed: 0.008,
      material: new THREE.MeshBasicMaterial({
        map: this.assetsManager.loadedItems.rotationBorder2,
        transparent: true,
        opacity: 1,
        side: THREE.DoubleSide,
        depthWrite: false,
      }),
      position: new THREE.Vector3(...center, 0.34),
    })
    plane02.mesh.renderOrder = 6
    plane02.join()
  }
  // 创建城市标签
  createLabel() {
    this.label2d = new Label2d(this)
    this.mainMap.coordinates = this.mainMap.coordinates.map(item => {
      return {
        ...item,
        value: random(10, 100),
      }
    })
    let geoProjection = ''
    if (this.isChina) {
      geoProjection = geoMercator().center(config.center).scale(17).translate([0, 0]) // 将经纬度转投影成坐标
    } else {
      geoProjection = geoMercator().center(config.center).scale(120).translate([0, 0]) // 将经纬度转投影成坐标
    }
    this.mainMap.coordinates.forEach(item => {
      if (!item.centroid || !item.center) {
        return false
      }
      let [x, y] = geoProjection(item.centroid || item.center)
      this.createLabelItem(item.name, new THREE.Vector3(x, -y, 0.6))
    })
  }
  createLabelItem(name, position, className = 'mapLabel') {
    const label = this.label2d.create(name, className)
    label.show(name, position)
    this.scene.add(label)
  }
  // 创建透明围墙
  createWall() {
    let data = transfromGeoJSON(this.assetsManager.loadedItems.province)
    let fzData = data.features.filter(item => item.properties.name === config.cityName)
    let coordinates = []
    fzData[0].geometry.coordinates[0].map(coords => {
      coords.map(cood => {
        let [x, y] = geoProjection(cood)
        coordinates.push(x, -y)
      })
    })
    let wall = new Wall(this, {
      coordinates: coordinates,
      height: 1.2, //高度
      renderOrder: 10,
      material: new THREE.MeshBasicMaterial({
        color: 0x158ef4,
        side: THREE.DoubleSide,
        transparent: true,
        depthTest: false,
        opacity: 0.2,
      }),
    })
    wall.mesh.position.z += 0.81
    wall.join()
  }
  // 创建波纹shader
  createPlane() {
    //

    let shaderMaterial = new SpreadShader(this, {
      radius: 0.0,
      center: new THREE.Vector3(...center, 0),
      width: 3.0,
      maxTime: 4.0,
      speed: 40.0,
      color: new THREE.Color('#0cb7f9'),
      material: new THREE.MeshLambertMaterial({
        color: 0x034158,
        transparent: true,
        depthWrite: false,
      }),
    })
    let [x0, y0] = center
    let geoArr = []
    let cityBox = {
      min: { x: -9.402891159057617, y: -9.644509315490723, z: 0.3000000029802322 },
      max: { x: 12.942660331726074, y: 6.478987216949463, z: 0.799999988079071 },
    }
    for (let i = 0; i < 5000; i++) {
      let x = random(x0 - 50, x0 + 50)
      let y = random(y0 - 50, y0 + 50)
      let z = random(1, 5) / 10
      if (x > cityBox.min.x && x < cityBox.max.x && y > cityBox.min.y && y < cityBox.max.y) {
        continue
      }

      let w = random(1, 20) / 30
      let cubeGeo = new THREE.BoxBufferGeometry(w, w, w)
      cubeGeo.rotateX(THREE.MathUtils.degToRad(random(0, 360)))
      cubeGeo.rotateY(THREE.MathUtils.degToRad(random(0, 360)))
      cubeGeo.rotateZ(THREE.MathUtils.degToRad(random(0, 360)))
      cubeGeo.translate(x, y, z + w)
      geoArr.push(cubeGeo)
    }
    var allGeometry = mergeBufferGeometries(geoArr)
    // var cubeMesh = new THREE.Mesh(allGeometry, new THREE.MeshBasicMaterial({ color: 0xffffff })) //网格模型对象
    var cubeMesh = new THREE.Mesh(allGeometry, shaderMaterial.getMaterial()) //网格模型对象
    cubeMesh.position.set(...center, 0)
    this.scene.add(cubeMesh)
    const geo = new THREE.PlaneBufferGeometry(1000, 1000)
    const mesh = new THREE.Mesh(geo, shaderMaterial.getMaterial())
    mesh.renderOrder = -5
    this.scene.add(mesh)
  }
  // 创建柱状图
  createBar(data) {
    console.log('开始画柱状图~~~~~~~~~~~~~~')
    this.label2d = new Label2d(this)

    let column = {
      coordinates: [],
      box: this.mainMap.box,
    }
    for (let i = 0; i < this.mainMap.coordinates.length; i++) {
      for (let j = 0; j < data.length; j++) {
        if (this.mainMap.coordinates[i]['name'] == data[j]['key']) {
          column.coordinates.push({
            ...this.mainMap.coordinates[i],
            value: data[j]['allCount'],
            warn: data[j]['warnCount'],
            name: data[j]['key'],
          })
        }
      }
    }

    this.mainMap.coordinates = this.mainMap.coordinates.map(item => {
      return {
        ...item,
        value: random(10, 100),
      }
    })

    const barGroup = new THREE.Group()
    // 最大高度
    const height = 4.0
    // 渐变材质
    // const material = new GradientShader(this, {
    //   height: height,
    //   color1: new THREE.Color('#00ffff'),
    //   color2: new THREE.Color('#ffffff'),
    //   material: new THREE.MeshBasicMaterial({
    //     transparent: true,
    //     side: THREE.DoubleSide,
    //     opacity: 0.5,
    //   }),
    // }).getMaterial()

    // 普通材质
    const material = new THREE.MeshBasicMaterial({
      map: this.assetsManager.loadedItems.column,
      color: 0x00ffff,
      transparent: true,
      depthWrite: false,
      side: THREE.DoubleSide,
    })

    const materialWarn = new THREE.MeshBasicMaterial({
      map: this.assetsManager.loadedItems.column,
      color: 0xff0000,
      transparent: true,
      depthWrite: false,
      side: THREE.DoubleSide,
    })

    // const materialWarn = new GradientShader(this, {
    //   height: height,
    //   color1: new THREE.Color('#FF0000'),
    //   color2: new THREE.Color('#ffffff'),
    //   material: new THREE.MeshBasicMaterial({

    //     transparent: true,
    //     side: THREE.DoubleSide,
    //     opacity: 0.5,
    //   }),
    // }).getMaterial()

    // 获取z轴的位置
    let { z } = column.box.box3.max
    // value最大值
    let cityArea = _.orderBy(column.coordinates, ['value'], ['desc'])
    let max = _.maxBy(column.coordinates, function (o) {
      return o.value
    }).value
    // 循环创建bar
    cityArea.map(item => {
      if (!item.centroid || !item.center) {
        return false
      }
      // 网格
      let geoHeight = height * (item.value / max)

      const geo = new THREE.PlaneBufferGeometry(geoHeight / 6.219, geoHeight)
      // 柱体旋转90度，垂直于Y轴
      geo.rotateX(Math.PI / 2)
      // 柱体的z轴移动高度一半对齐中心点
      geo.translate(0, 0, geoHeight / 2)

      const mesh = new THREE.Mesh(geo, item.warn > 0 ? materialWarn : material)
      mesh.renderOrder = 15
      let areaBar = mesh
      let geoProjection = ''
      if (this.isChina) {
        geoProjection = geoMercator().center(config.center).scale(17).translate([0, 0]) // 将经纬度转投影成坐标
      } else {
        geoProjection = geoMercator().center(config.center).scale(120).translate([0, 0]) // 将经纬度转投影成坐标
      }
      let [x, y] = geoProjection(item.centroid || item.center)
      areaBar.position.set(x, -y, z)
      areaBar.name = item.name
      let areaBar02 = areaBar.clone()
      areaBar02.name = 'createLightPillar02'
      areaBar02.rotateZ(Math.PI / 2)
      barGroup.add(areaBar, areaBar02)
    })
    barGroup.scale.set(this.scale, this.scale, 1)
    let center = this.mainMap.box.center
    if (this.isChina) {
      barGroup.position.x = -+center.x * this.scale + 0.1
      barGroup.position.y = -+center.y * this.scale + 0.4
    } else {
      barGroup.position.x = -+center.x * this.scale
      barGroup.position.y = -+center.y * this.scale
    }

    barGroup.name = '柱状图'
    this.columnGroup = { ...barGroup }
    this.scene.add(barGroup)
  }
  // 导出模型
  exportModel() {
    exportGLTF(this.scene)
  }

  debounce(callback, delay = 5) {
    let timer = null
    return function () {
      // 因为这里返回出去的方法是被 外部元素调用的,
      // 所以这里的 this 就指向了外部元素
      let self = this
      // 每个函数内部都一个属性 arguments, 其中包括了所有外部调用这个函数传递进来的参数
      let args = arguments
      timer && clearTimeout(timer)
      timer = setTimeout(function () {
        // apply: 作用就是改变方法内部this的指向, 并能将参数传递给该方法, 最后立即执行这个函数
        callback.apply(self, args)
      }, delay)
    }
  }

  destroyThreejs() {
    console.log('threejs被销毁了~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~')
    if (!this.renderer) {
      return
    }
    try {
      this.resizer.removeListenerResize()
      this.renderer.dispose()
      this.renderer.forceContextLoss()
      this.renderer.content = null
      let gl = this.renderer.domElement.getContext(this.el)
      if (gl && gl.getExtension('WEBGL_lose_context')) {
        gl.getExtension('WEBGL_lose_context').loseContext()
      }
      this.renderer = null
      this.camera = null
      this.scene.traverse(child => {
        if (child.material) {
          if (child.material instanceof Array) {
            child.material.forEach(item => {
              item.dispose()
            })
          } else {
            child.material.dispose()
          }
        }
        if (child.geometry) {
          child.geometry.dispose()
        }
        child = null
      })
      this.scene = null
    } catch (e) {
      console.error('Failed to destroy threejs', e)
    }
  }
}
